//
//  client_service_request.hpp
// ~~~~~~~~~~~~~~~~~~~~~
//
// Copyright (c) 2013-2014 Razvan Coca (razvan dot coca at  gmail dot com)
// This is mostly generated code. Generator is distributed under GPL. Edit it to suit your needs.
// 


#ifndef client_service_request_hpp
#define client_service_request_hpp
#include <boost/bind.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/enable_shared_from_this.hpp>
#include <boost/asio.hpp>
#include <boost/bind/protect.hpp>

#include "patterns/command.hpp"
#include "patterns/handlers.hpp"

#include "logging/logging.hpp"

namespace pcmd=patterns::command;
namespace phdl=patterns::handlers;
namespace ba=boost::asio;
namespace bs=boost::system;
namespace bt=boost::posix_time;

#include "components/defs/util_types.hpp"
#include "components/defs/client_processor.hpp"
#include "components/protocol/create_enc_service_request.hpp"
#include "components/network/send_enc_pb_message.hpp"
#include "components/defs/handler_types.hpp"

namespace components{
namespace protocol{



class client_service_request :public boost::enable_shared_from_this<client_service_request>, private boost::noncopyable
{
private:
    std::string name_;

    ba::io_service& ios_;

    crypto_buf_t& iv_;

    crypto_buf_t& key_;

    ba::ip::udp::socket& msocket_;

    udp_endpoint_t& local_if_;

    udp_endpoint_t& mgroup_;

    std::string send_buf_;

    stats_message_client_processor& message_processor_;

    boost::shared_ptr<components::network::send_enc_pb_message> send_enc_pb_message_;

    boost::shared_ptr<components::protocol::create_enc_service_request> create_enc_service_request_;

    client_service_request (ba::io_service& ios, crypto_buf_t& iv, crypto_buf_t& key, ba::ip::udp::socket& msocket,
                            udp_endpoint_t& local_if, udp_endpoint_t& mgroup,
                            stats_message_client_processor &message_processor) ;

public:
    typedef boost::shared_ptr<client_service_request> pointer;

    bool cancel () ;

    static boost::shared_ptr<client_service_request> create (ba::io_service& ios, crypto_buf_t& iv, crypto_buf_t& key,
                                                             ba::ip::udp::socket& msocket, udp_endpoint_t& local_if, udp_endpoint_t& mgroup,
                                                              stats_message_client_processor &message_processor) ;

    void handle_create_enc_service_request (const crypto_error& eec) ;

    void handle_send_enc_pb_message (const bs::error_code& ec, std::size_t bytes_transferred) ;

    void init_components () ;

    virtual  ~client_service_request () ;
    template<typename Handler >
    void adapt_send(Handler handler,const bs::error_code& ec, std::size_t bytes_transferred)
    {
        CryptoPP::Exception eec(CryptoPP::Exception::NOT_IMPLEMENTED,std::string("Success"));
        handler(ec,eec);
    }
    template<typename Handler >
    void adapt_encrypt(Handler handler,const crypto_error& eec)
    {
        bs::error_code ec;
        handler(ec,eec);
    }
    template<typename Handler >
    bool exec(stats_message_t& req, Handler handler) {
        try{
            LOG(INFO)<<name_<<"::"<<__FUNCTION__;

            phdl::crypto_handler_t
                    bound_handle_create_enc_service_request = boost::bind(&client_service_request::handle_create_enc_service_request,shared_from_this(),_1);
            phdl::transfer_handler_t
                    bound_handle_send_enc_pb_message = boost::bind(&client_service_request::handle_send_enc_pb_message,shared_from_this(),_1,_2);


            phdl::transfer_handler_t
                    top_send=boost::bind(&client_service_request::adapt_send<Handler>,shared_from_this(),boost::protect(handler),_1,_2);
            phdl::crypto_handler_t
                    top_encr=boost::bind(&client_service_request::adapt_encrypt<Handler>,shared_from_this(),boost::protect(handler),_1);


            phdl::transfer_handler_t composed_send=phdl::branch_compose(bound_handle_send_enc_pb_message,top_send,{});
            pcmd::action_t op_send_enc_pb_message = pcmd::wrap(send_enc_pb_message_,boost::ref(send_buf_),composed_send);

            auto composed_encr=phdl::branch_compose(bound_handle_create_enc_service_request,top_encr,op_send_enc_pb_message,{0});
            pcmd::action_t op_create_enc_service_request = pcmd::wrap(create_enc_service_request_,boost::ref(req),boost::ref(send_buf_),composed_encr);


            return pcmd::invoke(op_create_enc_service_request);
        }
        catch(std::exception &e){
            LOG(WARNING)<<name_<<"::"<<__FUNCTION__<<":"<<e.what();
            cancel();
            return false;
        }
        
    }
};

}//end namespace protocol
}//end namespace components

#endif /*#ifdef client_service_request_hpp*/
